package org.wtframework.platform.web.mvc.action.impl;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.openredhead.springx.core.component.shiro.RedirectUrlSavedRequest;
import org.openredhead.springx.core.component.shiro.UserRealm;
import org.openredhead.springx.core.server.annotation.Property;
import org.openredhead.springx.core.server.manager.IBasicUserManager;
import org.openredhead.springx.core.server.manager.impl.ResetPasswordManager;
import org.openredhead.springx.core.server.model.IUser;
import org.openredhead.springx.core.server.model.IUserIdentity;
import org.openredhead.springx.core.server.model.impl.ResetPassword;
import org.openredhead.springx.core.server.service.Exceptions;
import org.openredhead.springx.core.server.service.FilePaths;
import org.openredhead.springx.core.server.service.Mails;
import org.openredhead.springx.core.server.util.DateUtils;
import org.openredhead.springx.core.server.util.RandomUtils;
import org.openredhead.springx.core.server.util.RegexUtils;
import org.openredhead.springx.core.web.mvc.support.ActionValueAssistant;
import org.openredhead.springx.core.web.service.Webs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.wtframework.platform.server.manager.IUserIdentityManager;
import org.wtframework.platform.server.manager.impl.UserActivateManager;
import org.wtframework.platform.server.model.impl.User;
import org.wtframework.platform.server.model.impl.UserActivate;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

@Controller
@SuppressWarnings("rawtypes")
public class AuthorizationActionController {

	private String frogetPasswordTemplate = "";

	private String activateUserTemplate = "";

	@Autowired
	private IBasicUserManager userManager;

	@Autowired
	private ResetPasswordManager resetPasswordManager;

	@Autowired
	private UserActivateManager userActivateManager;
	
	@Autowired
	private IUserIdentityManager userIdentityManager;

	@Autowired
	private Mails mails;

	@Autowired
	private UserRealm userRealm;
	
	@Property(name = "sys.project.name")
	private String SYSTEM_NAME;
	
	@Property(name = "url.page.login")
	private String loginUrl;

	@PostConstruct
	private void onInitAction() {

		String frogetPasswordTemplatePath = FilePaths.getSystemRootPath() + File.separator + "WEB-INF" + File.separator + "files" + File.separator + "template" + File.separator + "mail" + File.separator + "frogetPassword.html";
		String activateUserTemplatePath = FilePaths.getSystemRootPath() + File.separator + "WEB-INF" + File.separator + "files" + File.separator + "template" + File.separator + "mail" + File.separator + "activateUser.html";

		File frogetPasswordTemplateFile = new File(frogetPasswordTemplatePath);
		File activateUserTemplateFile = new File(activateUserTemplatePath);

		if (!frogetPasswordTemplateFile.exists()) Exceptions.logException(this, "onInitAction", new RuntimeException("找不到忘记密码的邮件模板文件：" + frogetPasswordTemplatePath));

		if (!activateUserTemplateFile.exists()) Exceptions.logException(this, "onInitAction", new RuntimeException("找不到忘记密码的邮件模板文件：" + activateUserTemplatePath));

		try {

			List<String> lines = Files.readLines(frogetPasswordTemplateFile, Charset.forName("UTF-8"));

			List<String> lines2 = Files.readLines(activateUserTemplateFile, Charset.forName("UTF-8"));

			for (String line : lines)
				frogetPasswordTemplate = frogetPasswordTemplate + line + "\n";

			for (String line1 : lines2)
				activateUserTemplate = activateUserTemplate + line1 + "\n";

		} catch (IOException e) {
			Exceptions.logException(this, "onInitAction", e);
		}

	}

	@RequestMapping("/login")
	public String login(HttpServletRequest request, ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		String errorClass = actionValueAssistant.getString(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);

		if (IncorrectCredentialsException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "帐号信息有误！");

		} else if (UnknownAccountException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "帐号不存在！");

		} else if (LockedAccountException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "帐号已被锁定！");

		} else if (ExpiredCredentialsException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "帐号已过期！");

		} else if (DisabledAccountException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "帐号未被开通，无法登录！");

		} else if (ExcessiveAttemptsException.class.getName().equals(errorClass)) {

			modelMap.put("errorMsg", "你连续登录该帐号5次失败！请过5分钟后再试。");

		} else {

			if (!Strings.isNullOrEmpty(errorClass)) {

				modelMap.put("errorMsg", "帐号未被开通，无法登录！");

			}

		}

		return "admin/auth/login";

	}

	@RequestMapping("/unauth")
	public String unauth(ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		return "admin/auth/unauth";

	}

	@RequestMapping("/loginRedirect")
	public String loginRedirect(HttpServletRequest request, ModelMap modelMap) throws UnsupportedEncodingException {

//		import java.net.URLDecoder;
//		import java.net.URLEncoder;
		
		String redirectUrl = request.getParameter("redirectUrl");

		
		
		if (!Strings.isNullOrEmpty(redirectUrl)) {
			RedirectUrlSavedRequest savedRequest = new RedirectUrlSavedRequest(request, redirectUrl);
			Webs.getSession().setAttribute(WebUtils.SAVED_REQUEST_KEY, savedRequest);
		}

		return "redirect:" + loginUrl;

	}

	@RequestMapping("/forgetPassword")
	public String forgetPassword(ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		modelMap.put("isSuccess", 1);

		return "auth/forgetPassword";

	}

	@RequestMapping("/forgetPassword/email")
	public String forgetPasswordEmail(HttpServletRequest request, ModelMap modelMap, ActionValueAssistant actionValueAssistant) throws UnsupportedEncodingException, MessagingException {

		String userInfo = actionValueAssistant.getString("userInfo");

		if (userInfo == null) {
			modelMap.put("errorMsg", "请输入用户名或邮箱！");
			modelMap.put("isSuccess", 1);
			return "auth/forgetPassword";
		}

		if ("admin".equals(userInfo)) {
			modelMap.put("errorMsg", "不存在用户名或邮箱！");
			modelMap.put("isSuccess", 1);
			return "auth/forgetPassword";
		}
		
		String emailRegx = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";

		String email = userInfo;

		IUser user;

		if (!RegexUtils.isRegexMatch(emailRegx, userInfo)) {

			user = userManager.load(userInfo);

			if (user == null) {
				modelMap.put("errorMsg", "找不到相应的用户！");
				modelMap.put("isSuccess", 1);
				return "auth/forgetPassword";
			}

			if (Strings.isNullOrEmpty(user.getEmail()) || !RegexUtils.isRegexMatch(emailRegx, user.getEmail())) {
				modelMap.put("errorMsg", "找不到用户的电子邮箱！");
				modelMap.put("isSuccess", 1);
				return "auth/forgetPassword";
			}

			email = user.getEmail();

		} else {

			user = (IUser) userManager.findUnique(userInfo, userInfo);

			if (user == null) {
				modelMap.put("errorMsg", "找不到相应的用户！");
				modelMap.put("isSuccess", 1);
				return "auth/forgetPassword";
			}

		}

		modelMap.put("isSuccess", 2);
		modelMap.put("userEmail", email);
		modelMap.put("user", user);
		return "auth/forgetPassword";

	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/forgetPassword/email/{id}")
	public String sendEmailForPassword(@PathVariable Long id, HttpServletRequest request, ModelMap modelMap, ActionValueAssistant actionValueAssistant) {
		
		
		IUser user = (IUser) userManager.load(id);
		
		if(user ==  null) {
			modelMap.put("errorMsg", "找不到相应的用户！");
			modelMap.put("isSuccess", 1);
			return "auth/forgetPassword";
		}	
		String emailRegx = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
		if (Strings.isNullOrEmpty(user.getEmail()) || !RegexUtils.isRegexMatch(emailRegx, user.getEmail())) {
			modelMap.put("errorMsg", "找不到用户的电子邮箱！");
			modelMap.put("isSuccess", 1);
			return "auth/forgetPassword";
		}
		String email =  user.getEmail();
		String code = RandomUtils.getDateTimeRandomString() + RandomUtils.geRandom();

		String url = Webs.getBasicUrl(request) + "/resetPassword/" + code;

		long expireTime = (new Date()).getTime() + (30L * 60 * 1000);

		String emailContent = MessageFormat.format(frogetPasswordTemplate, SYSTEM_NAME, url, user.getUsername(), DateUtils.getDateTimeString(new Date(expireTime)));

		List<String> emailList = Lists.newArrayList(email);

		try {
			mails.sendEmail("重置用户密码", emailContent, emailList);
		} catch (Exception e) {
			modelMap.put("errorMsg", "发送邮件异常，请稍后再试！");
			modelMap.put("isSuccess", 1);
			return "auth/forgetPassword";
		}

		ResetPassword resetPassword = new ResetPassword();
		resetPassword.setCode(code);
		resetPassword.setUsername(user.getUsername());
		resetPassword.setExpireTime(new Date(expireTime));

		resetPasswordManager.save(resetPassword);
		
		modelMap.put("isSuccess", 3);
		modelMap.put("user", user);
		return "auth/forgetPassword";
	}

	@RequestMapping("/resetPassword/{code}")
	public String resetPasswordCode(@PathVariable String code, ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		ResetPassword resetPassword = resetPasswordManager.findUnique("code", code);

		if (resetPassword == null) {
			modelMap.put("errorMsg", "你的链接信息有误！请重新输入你的邮箱。");
			modelMap.put("isSuccess", 1);
			return "admin/auth/forgetPassword";
		}

		if ((new Date()).getTime() > resetPassword.getExpireTime().getTime()) {
			modelMap.put("errorMsg", "链接已经过期！请重新输入你的邮箱。");
			modelMap.put("isSuccess", 1);
			return "admin/auth/forgetPassword";
		}

		modelMap.put("username", resetPassword.getUsername());
		modelMap.put("restetCode", code);

		return "admin/auth/resetPassword";

	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/resetPassword")
	public String resetPassword(ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		String code = actionValueAssistant.getString("restetCode");

		if (Strings.isNullOrEmpty(code)) {
			modelMap.put("exception", "你的信息有误，密码无法修改。");
			return "admin/auth/resetPassword";
		}

		ResetPassword resetPassword = resetPasswordManager.findUnique("code", code);

		if (resetPassword == null) {
			modelMap.put("exception", "你的信息有误，密码无法修改。");
			return "admin/auth/resetPassword";
		}

		modelMap.put("restetCode", code);

		modelMap.put("username", resetPassword.getUsername());

		String password1 = actionValueAssistant.getString("password1");

		if (Strings.isNullOrEmpty(password1)) {
			modelMap.put("errorMsg1", "必须填写密码！");
			actionValueAssistant.addToModelMap(modelMap);
			return "admin/auth/resetPassword";
		}

		String password2 = actionValueAssistant.getString("password2");

		if (!password1.equals(password2)) {
			modelMap.put("errorMsg2", "两次填写的密码并不相同，请重新填写！");
			actionValueAssistant.addToModelMap(modelMap);
			return "admin/auth/resetPassword";
		}

		String password = DigestUtils.md5Hex(password1);

		IUser user = userManager.load(resetPassword.getUsername());

		user.setPassword(password);

		userManager.save(user);

		resetPasswordManager.delete(resetPassword);

		modelMap.put("isSuccess", true);

		return "admin/auth/resetPassword";

	}

	@RequestMapping("/userRegister")
	public String userRegisterUI(ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		modelMap.put("isSuccess", 1);

		return "admin/auth/userRegister";

	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/userRegister/user")
	public String userReisterSubmit(HttpServletRequest request, ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		String username = actionValueAssistant.getString("username");
		String password = actionValueAssistant.getString("password");
		String nickname = actionValueAssistant.getString("nickname");
		String email = actionValueAssistant.getString("email");
		String phoneNumber = actionValueAssistant.getString("phoneNumber");

		IUser user = new User();
		user.setUsername(username);
		user.setPassword(DigestUtils.md5Hex(password));
		user.setNickname(nickname);
		user.setEmail(email);
		user.setPhoneNumber(phoneNumber);
		user.setLocked(true);
		
		//随机生成头像
		String[] imageArray = new String[]{"tou_a.jpg", "tou_b.jpg", "tou_c.jpg", "tou_d.jpg", "tou_e.jpg", "tou_f.jpg", "tou_g.jpg", "tou_h.jpg"};
		Random rand = new Random();
		Integer tem = rand.nextInt(8);
		String imagestr = "/style/back/image/" + imageArray[tem];
		user.setImageUrl(imagestr);
		// user.setParentId(1);
		if (userManager.find("username", user.getUsername()).getCount() > 0) {
			modelMap.put("errorMsg_user", "<i class='ui-tiptext-icon iconfont' title='出错'>&#xF045;</i>用户名已存在，请重新填写！");
			modelMap.put("isSuccess", 1);
			actionValueAssistant.addToModelMap(modelMap);
			return "admin/auth/userRegister";
		}

		
		String code = RandomUtils.getDateTimeRandomString() + RandomUtils.geRandom();

		String url = Webs.getBasicUrl(request) + "/userRegister/" + code;

		long expireTime = (new Date()).getTime() + (30L * 60 * 1000);

		String emailContent = MessageFormat.format(activateUserTemplate, SYSTEM_NAME, url, user.getUsername(), DateUtils.getDateTimeString(new Date(expireTime)));

		try {
			mails.sendEmail("用户激活", emailContent, user.getEmail());
		} catch (Exception e) {
			modelMap.put("errorMsg_email", "<i class='ui-tiptext-icon iconfont' title='出错'>&#xF045;</i>不存在邮箱地址，密码重置失败！");
			actionValueAssistant.addToModelMap(modelMap);
			return "admin/auth/userRegister";
		}
		
		userManager.save(user);
		
		UserActivate userActivate = new UserActivate();
		userActivate.setCode(code);
		userActivate.setUsername(username);

		userActivateManager.save(userActivate);
		modelMap.put("isSuccess", 2);
		modelMap.put("email", email);
		return "admin/auth/userRegister";
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/userRegister/{code}")
	public String userRegisterCode(@PathVariable String code, ModelMap modelMap, ActionValueAssistant actionValueAssistant) {

		UserActivate userActivate = userActivateManager.findUnique("code", code);

		if (userActivate == null) {
			modelMap.put("errorMsg", "你的链接信息有误！请重新打开链接。");
			modelMap.put("isSuccess", 3);
			return "admin/auth/userRegister";
		}

		IUser user = userManager.load(userActivate.getUsername());
		if (user == null) {
			modelMap.put("errorMsg", userActivate.getUsername() + "用户审批不过，已经删除！");
			modelMap.put("isSuccess", 3);
			return "admin/auth/userRegister";
		}		
		if (!userActivate.getActivate()) {
			userActivate.setActivateTime(new Date());
			userActivate.setActivate(true);
			userActivateManager.save(userActivate);
		}		
		if(user.getIdentityId() == null) {
			IUserIdentity userIdentity = userIdentityManager.getDefalutUserIdentity();
			if(userIdentity!= null) {
				user.setIdentityId(userIdentity.getId());
			}
			user.setLocked(false);
			userManager.save(user);
		}
		if(userActivate.getActivate() && !user.isEnabled()) {
			modelMap.put("errorMsg", user.getUsername() + "已经注册成功，请等待管理员审批！");
			modelMap.put("isSuccess", 4);
			return "admin/auth/userRegister";
		}

		modelMap.put("username", user.getUsername());
		modelMap.put("isSuccess", 5);

		return "admin/auth/userRegister";

	}
	
	@RequestMapping("/updateUserPassword")
	public String updateUserPassword(){
		
		return "admin/auth/updatePassword";
	}
	
}
